#include "RedNeuronal.h"

RedNeuronal::RedNeuronal(MultiLayerPerceptron* mlp) {
    this->mlp = mlp;
    this->filtrar();

}

RedNeuronal::~RedNeuronal() {
}

void RedNeuronal::aprender() {
    // Cero
    this->aprende("Aprender/0.bmp", 0);
    // Uno
    this->aprende("Aprender/1.bmp", 1);
    // dos
    this->aprende("Aprender/2.bmp", 2);
    // tres
    this->aprende("Aprender/3.bmp", 3);
    // cuatro
    this->aprende("Aprender/4.bmp", 4);
    // cinco
    this->aprende("Aprender/5.bmp", 5);
    // seis
    this->aprende("Aprender/6.bmp", 6);
    // siete
    this->aprende("Aprender/7.bmp", 7);
    // ocho
    this->aprende("Aprender/8.bmp", 8);
    // nueve
    this->aprende("Aprender/9.bmp", 9);
    // punto
    this->aprende("Aprender/punto.bmp", 21);
    // coma
    this->aprende("Aprender/coma.bmp", 22);
   
}

void RedNeuronal::aprende(string path, float salida) {
    // Declaro variables
    ProcesadorImagen* procesador = new ProcesadorImagen();
    long int ancho = 0;
    long int alto = 0;
    long int despl = 0;
    long int tamanio = 0;

    // Levanto el vector con la info de la imagen
    procesador->levantarImagenEnMatrizPixeles(path.c_str(), &ancho, &alto, &despl);
    int* vector = procesador->obtenerVector(ancho, alto,ancho,0,alto,0);
    tamanio = (alto * ancho);

    // Declaro y completo las variables a guardar en la Red
    float input[tamanio];
    float desired_output = salida;
    for (int i = 0; i <= tamanio; ++i) {
        input[i] = vector [i];
    }

    // Entreno la red
    this->mlp->train(input, &desired_output);
}

string RedNeuronal::interpretar(string path) {
    // Declaro variables
    ProcesadorImagen* procesador = new ProcesadorImagen();
    long int ancho = 0;
    long int alto = 0;
    long int despl = 0;
    long int tamanio = 0;
    string salida;
    string oss;
    // Levanto el vector con la info de la imagen
    procesador->levantarImagenEnMatrizPixeles(path.c_str(), &ancho, &alto, &despl);
    procesador->boundingBox(path, ancho, alto);
    procesador->verFrames();
    
    vector<frame> imagenes = procesador->getFrames();
    vector<frame>::iterator it = imagenes.begin();
    
    int anchoAux, altoAux;
    for (; it != imagenes.end(); it++) {
        
        anchoAux = (*it).xMax - (*it).xMin;
        altoAux = (*it).yMax - (*it).yMin;
        int* vector = procesador->obtenerVector(anchoAux, altoAux,(*it).xMax,(*it).xMin,(*it).yMax,(*it).yMin );
        tamanio = (altoAux * anchoAux);
        // Declaro y completo las variables a guardar en la Red
        float* input = (float*) malloc(sizeof (float) *tamanio);
        float output = 0;
        for (int i = 0; i <= tamanio; ++i) {
                input[i] = vector [i];
        }
        // Obtengo resultado de la Red
        oss += this->mlp->compute(input, &output, tamanio);
    }
    
    delete procesador;
    salida = oss;
    return salida;
}

void RedNeuronal::guardarRed()
{
      // save the network on a text file
	ofstream savefile("net.txt");
	mlp->save(savefile);
	savefile.close();
}

